import LoadingVue from './TLoading.vue'
import { createApp } from 'vue'
import type { DirectiveBinding, Directive } from 'vue'
import type { LoadingProps, LoadingType } from './TLoading.vue'

export type VLoading = Directive<LoadingEl, boolean>

interface LoadingEl extends HTMLElement {
  loadingInstance: HTMLElement | null
}

const removeLoading = (el: LoadingEl) => {
  if (el.loadingInstance) {
    el.loadingInstance.remove()
    el.loadingInstance = null
  }
}

const initLoading = (el: LoadingEl, binding: DirectiveBinding): void => {
  const loadingText = el.getAttribute('ttt-loading-text')
  const loadingTextColor = el.getAttribute('ttt-loading-text-color')
  const loadingColor = el.getAttribute('ttt-loading-color')
  const loadingType = el.getAttribute('ttt-loading-type')
  const isFull = binding.modifiers?.full
  const parentPosition = el.style.position
  const props: Partial<LoadingProps> = {}
  if (loadingText) props.text = loadingText
  if (loadingTextColor) props.textColor = loadingTextColor
  if (loadingColor) props.bgColor = loadingColor
  if (loadingType && ['wave', 'rainbow'].includes(loadingType)) {
    props.loadingType = loadingType as LoadingType
  }
  if (parentPosition === '') el.style.position = 'relative'
  if (binding.value) {
    if (!el.loadingInstance) {
      const dom: HTMLElement = document.createElement('div')
      dom.style.width = '100%'
      dom.style.height = '100%'
      dom.style.position = isFull ? 'fixed' : 'absolute'
      dom.style.left = '0'
      dom.style.top = '0'
      el.appendChild(dom)
      createApp(LoadingVue, props).mount(dom)
      el.loadingInstance = dom
    }
  } else {
    removeLoading(el)
  }
}

const vLoading: VLoading = {
  mounted(el: LoadingEl, binding: DirectiveBinding) {
    initLoading(el, binding)
  },
  updated(el: LoadingEl, binding: DirectiveBinding) {
    initLoading(el, binding)
  },
  unmounted(el: LoadingEl) {
    removeLoading(el)
  }
}

export default vLoading
